package rctgl.park.sv4;

import rctgl.util.StreamUtils;

import java.io.IOException;
import java.io.ByteArrayInputStream;

import panoramic.PanoScene;

import rctgl.park.sv4.*;
import rctgl.ICompilable;

public class SV4Park
{
	private static int PARK_WIDTH = 128;
	private static int PARK_HEIGHT = 128;
	
	private PanoScene m_scene = new PanoScene();
	
	private boolean m_optimizeScene = true;
	
	
	private SV4ParkTile[][] m_parkTiles = new SV4ParkTile[PARK_WIDTH][PARK_HEIGHT];
	
	public SV4Park()
	{
		for(int i=0; i<PARK_WIDTH; i++)
			for(int j=0;j<PARK_HEIGHT;j++)
				m_parkTiles[i][j] = new SV4ParkTile();
		
		
	}
	
	public PanoScene getScene()
	{
		return m_scene;
	}
	
	public void loadFromStream(ByteArrayInputStream stream) throws IOException
	{
		int gameMonth = StreamUtils.readInt16(stream);
		int gameDay = StreamUtils.readInt16(stream);
		
		int gameTime = StreamUtils.readInt32(stream);
		int pseudoRandom0 = StreamUtils.readInt32(stream);
		int pseudoRandom1 = StreamUtils.readInt32(stream);
		
		for(int i=0; i<PARK_WIDTH; i++)
		{
			for(int j=0; j<PARK_HEIGHT; j++)
			{
				//System.out.println(i + ", " + j);
				m_parkTiles[i][j].setCoords(i, j);
				m_parkTiles[i][j].loadFromStream(stream);
				
				
			}
		}
		
		
	}

	public void compile()
	{
		compileSurface();
		//compileEdges();
		compileWater();
		//compilePaths();
		
		System.out.println("poly count=" + m_scene.getObjectCount());
		
		
	}
	
	private void compileSurface()
	{
		for(int i=0; i<PARK_WIDTH; i++)
		{
			for(int j=0; j<PARK_HEIGHT; j++)
			{
				SV4Surface curSurface = m_parkTiles[i][j].getSurface();
				if(curSurface.isSurfaceCompiled())
					continue;
				
				if(m_optimizeScene && curSurface.isExtendable())
				{
				
					int xStretchArea, xStretchXOff, xStretchZOff;
					int zStretchArea, zStretchXOff, zStretchZOff;
					
					//first stretch in x direction
					for(xStretchXOff=i; xStretchXOff<PARK_WIDTH; xStretchXOff++)
					{
						SV4Surface surf = m_parkTiles[xStretchXOff][j].getSurface();
						if(surf.isSurfaceCompiled() ||
								!curSurface.extendsPiece( surf, xStretchXOff-i, 0))
							break;
					}
					
					boolean goodPatch = true;
					
					
					xStretchZOff=j;
					
					
					for(xStretchZOff=j; xStretchZOff<PARK_HEIGHT && goodPatch; xStretchZOff++)
					{
						for(int a=i; a<xStretchXOff && goodPatch; a++)
						{
							SV4Surface surf = m_parkTiles[a][xStretchZOff].getSurface();
							if(surf.isSurfaceCompiled() ||
									!curSurface.extendsPiece( surf, a-i+1, xStretchZOff-j+1))
							{
								goodPatch=false;
							}
							
						}
					}
					
					
					xStretchZOff--;
					
					
					
					
					for(int a=i; a<xStretchXOff; a++)
					{
						for(int b=j; b<xStretchZOff; b++)
							m_parkTiles[a][b].getSurface().setIsSurfaceCompiled(true);
					}
								
					
					curSurface.compileSurface(m_scene, (xStretchXOff-i), (xStretchZOff-j));
				}
				else
				{
					curSurface.setIsSurfaceCompiled(true);
					curSurface.compileSurface(m_scene, 1, 1);
					
				}
				
				
			}
		}
		
		
	}
	
	private void compileWater()
	{
		for(int i=0; i<PARK_WIDTH; i++)
		{
			for(int j=0; j<PARK_HEIGHT; j++)
			{
				SV4Surface curSurface = m_parkTiles[i][j].getSurface();
				if(curSurface.isWaterCompiled() || !curSurface.hasWater())
					continue;
				
				if(m_optimizeScene)
				{
				
					int xStretchArea, xStretchXOff, xStretchZOff;
					int zStretchArea, zStretchXOff, zStretchZOff;
					
					//first stretch in x direction
					for(xStretchXOff=i; xStretchXOff<PARK_WIDTH; xStretchXOff++)
					{
						SV4Surface surf = m_parkTiles[xStretchXOff][j].getSurface();
						if(surf.isWaterCompiled() ||
								!curSurface.extendsWater( surf, xStretchXOff-i, 0))
							break;
					}
					
					boolean goodPatch = true;
					
					
					xStretchZOff=j;
					
					
					for(xStretchZOff=j; xStretchZOff<PARK_HEIGHT && goodPatch; xStretchZOff++)
					{
						for(int a=i; a<xStretchXOff && goodPatch; a++)
						{
							SV4Surface surf = m_parkTiles[a][xStretchZOff].getSurface();
							if(surf.isWaterCompiled() ||
									!curSurface.extendsWater( surf, a-i+1, xStretchZOff-j+1))
							{
								goodPatch=false;
							}
							
						}
					}
					
					
					xStretchZOff--;
					
					
					
					
					for(int a=i; a<xStretchXOff; a++)
					{
						for(int b=j; b<xStretchZOff; b++)
							m_parkTiles[a][b].getSurface().setIsWaterCompiled(true);
					}
								
					
					curSurface.compileWater(m_scene, (xStretchXOff-i), (xStretchZOff-j));
				}
				else
				{
					curSurface.setIsWaterCompiled(true);
					curSurface.compileWater(m_scene, 1, 1);
					
				}
				
				
				
			}
		}
		
	}
	
	
	private void compileEdges()
	{
		for(int i=0; i<PARK_WIDTH-1; i++)
		{
			for(int j=0; j<PARK_HEIGHT-1; j++)
			{
				SV4Surface curSurface = m_parkTiles[i][j].getSurface();
				SV4Surface nextSurfaceUp = m_parkTiles[i][j+1].getSurface();
				SV4Surface nextSurfaceOver = m_parkTiles[i+1][j].getSurface();
				
				curSurface.compileNorthEdge(m_scene, nextSurfaceUp);
				curSurface.compileEastEdge(m_scene, nextSurfaceOver);
				
				
			}
		}
		
	}
	
	
	private void compilePaths()
	{
		for(int i=0; i<PARK_WIDTH; i++)
		{
			for(int j=0; j<PARK_HEIGHT; j++)
			{
				for(SV4Path curPath : m_parkTiles[i][j].getPaths())
				{
					curPath.compilePath(m_scene); //, 1, 1);
					
				}
				
			}
		}
		
	}
	
	

}
